package com.learning.demos;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author adolphw
 *
 * synchronized 和 reentrantlock的区别
 *
 * synchronized：
 * 1 关键字
 * 2 可正常退出 monitorenter monitorexit  不需要用户手动释放锁
 * 3 不可中断
 * 4 非公平锁
 * 5 绑定多个条件condition 不能  要么唤醒一个 要么全部
 *
 * reentrantlock：
 * 1 java juc类
 * 2 需要用户手动释放锁
 * 3 可以中断
 * 4 公平 非 都可以
 * 5 绑定多个条件condition 可以精确唤醒
 *
 * demo
 * A 打印10次  后通知B 打印15次 后通知C打印20次
 * 来10轮
 */
public class SyncAndReentrantLockDemo {

    public static void main(String[] args) {
        ShareResource shareResource = new ShareResource();

        new Thread(()->{
            shareResource.print5();
        },"A").start();

        new Thread(()->{
            shareResource.print10();
        },"B").start();

        new Thread(()->{
            shareResource.print15();
        },"C").start();
    }
}

class ShareResource{
    // a1 b2 c3
    private int num = 1;
    private Lock lock = new ReentrantLock();
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();

    public void print5() {
        lock.lock();

        try {
            while (num != 1) {
                condition1.await();
            }

            for (int i = 0; i <5 ; i++) {
                System.out.println(Thread.currentThread().getName() + "\t " + i);
            }

            num = 2;
            condition2.signal();
        } catch (Exception e) {
            e.printStackTrace();

        }finally {
            lock.unlock();
        }

    }

    public void print10() {
        lock.lock();

        try {
            while (num != 2) {
                condition1.await();
            }

            for (int i = 0; i <10 ; i++) {
                System.out.println(Thread.currentThread().getName() + "\t " + i);
            }

            num = 3;
            condition3.signal();
        } catch (Exception e) {
            e.printStackTrace();

        }finally {
            lock.unlock();
        }

    }

    public void print15() {
        lock.lock();

        try {
            while (num != 3) {
                condition1.await();
            }

            for (int i = 0; i <15 ; i++) {
                System.out.println(Thread.currentThread().getName() + "\t " + i);
            }

            num = 3;
            condition3.signal();
        } catch (Exception e) {
            e.printStackTrace();

        }finally {
            lock.unlock();
        }

    }
}
